import * as X6 from "@antv/x6";
import { Stencil } from '@antv/x6-plugin-stencil';
import { History } from '@antv/x6-plugin-history';
import { Keyboard } from '@antv/x6-plugin-keyboard';
import { Snapline } from '@antv/x6-plugin-snapline';
import { Transform } from '@antv/x6-plugin-transform';
import { Selection } from '@antv/x6-plugin-selection';
import { Clipboard } from '@antv/x6-plugin-clipboard';

const color = '#5F95FF';
// #region 初始化图形
const portAttrs = { circle: { r: 4, magnet: true, stroke: color, strokeWidth: 1, fill: '#fff', style: { visibility: 'hidden' } } }
const ports = {
	groups: {
		top: { position: 'top', attrs: portAttrs },
		right: { position: 'right', attrs: portAttrs },
		bottom: { position: 'bottom', attrs: portAttrs },
		left: { position: 'left', attrs: portAttrs }
	},
	items: [{ group: 'top' }, { group: 'right' }, { group: 'bottom' }, { group: 'left' }],
}

X6.Graph.registerNode('custom-rect', {
	inherit: 'rect',
	width: 72,
	height: 36,
	attrs: {
		body: { strokeWidth: 1, stroke: color, fill: '#EFF4FF' },
		text: { fontSize: 14, fill: '#262626' },
	},
	ports: { ...ports }
}, true)

X6.Graph.registerNode('custom-polygon', {
	inherit: 'polygon',
	width: 72,
	height: 36,
	attrs: {
		body: { strokeWidth: 1, stroke: color, fill: '#EFF4FF' },
		text: { fontSize: 14, fill: '#262626' },
	},
	ports: {
		...ports,
		items: [{ group: 'top', }, { group: 'bottom', }],
	}
}, true)

X6.Graph.registerNode('custom-circle', {
	inherit: 'circle',
	width: 48,
	height: 48,
	attrs: {
		body: { strokeWidth: 1, stroke: color, fill: '#EFF4FF' },
		text: { fontSize: 14, fill: '#262626' },
	},
	ports: { ...ports }
}, true)

X6.Graph.registerNode('custom-image', {
	inherit: 'rect',
	width: 52,
	height: 52,
	markup: [
		{ tagName: 'rect', selector: 'body' },
		{ tagName: 'image' },
		{ tagName: 'text', selector: 'label' }
	],
	attrs: {
		body: { stroke: color, fill: color },
		image: { width: 26, height: 26, refX: 13, refY: 16 },
		label: { refX: 3, refY: 2, textAnchor: 'left', textVerticalAnchor: 'top', fontSize: 12, fill: '#fff' },
	},
	ports: { ...ports },
}, true)

const createEdgeFunc = () => {
	return new X6.Shape.Edge({
		attrs: {
			line: {
				stroke: '#A2B1C3',
				strokeWidth: 2,
				targetMarker: { name: 'block', width: 12, height: 8 }
			}
		},
		zIndex: 0
	})
};

const initFlowNodes = (container, graph) => {
	let stencil = new Stencil({
		title: '流程图',
		target: graph,
		stencilGraphWidth: 200,
		stencilGraphHeight: 190,
		collapsable: true,
		groups: [
			{ title: '基础流程图', name: 'group1' },
			{ title: '系统设计图', name: 'group2', graphHeight: 250, layoutOptions: { rowHeight: 70 } }
		],
		layoutOptions: { columns: 2, columnWidth: 90, rowHeight: 55 }
	});
	container.appendChild(stencil.container);
	const r1 = graph.createNode({
		shape: 'custom-rect',
		label: '开始',
		attrs: { body: { rx: 18, ry: 18 } }
	})
	const r2 = graph.createNode({
		shape: 'custom-rect',
		label: '过程'
	})
	const r3 = graph.createNode({
		shape: 'custom-rect',
		attrs: { body: { rx: 6, ry: 6 } },
		label: '可选过程'
	})
	const r4 = graph.createNode({
		shape: 'custom-polygon',
		attrs: { body: { refPoints: '0,10 10,0 20,10 10,20' } },
		label: '决策'
	})
	const r5 = graph.createNode({
		shape: 'custom-polygon',
		attrs: { body: { refPoints: '10,0 40,0 30,20 0,20' } },
		label: '数据'
	})
	const r6 = graph.createNode({
		shape: 'custom-circle',
		label: '连接'
	})
	stencil.load([r1, r2, r3, r4, r5, r6], 'group1');

	const imageShapes = [
		{ label: 'Client', image: 'https://gw.alipayobjects.com/zos/bmw-prod/687b6cb9-4b97-42a6-96d0-34b3099133ac.svg' },
		{ label: 'Http', image: 'https://gw.alipayobjects.com/zos/bmw-prod/dc1ced06-417d-466f-927b-b4a4d3265791.svg' },
		{ label: 'Api', image: 'https://gw.alipayobjects.com/zos/bmw-prod/c55d7ae1-8d20-4585-bd8f-ca23653a4489.svg' },
		{ label: 'Sql', image: 'https://gw.alipayobjects.com/zos/bmw-prod/6eb71764-18ed-4149-b868-53ad1542c405.svg' },
		{ label: 'Clound', image: 'https://gw.alipayobjects.com/zos/bmw-prod/c36fe7cb-dc24-4854-aeb5-88d8dc36d52e.svg' },
		{ label: 'Mq', image: 'https://gw.alipayobjects.com/zos/bmw-prod/2010ac9f-40e7-49d4-8c4a-4fcf2f83033b.svg' }
	]
	const imageNodes = imageShapes.map((item) => {
		return graph.createNode({
			shape: 'custom-image',
			label: item.label,
			attrs: { image: { 'xlink:href': item.image } }
		})
	});
	stencil.load(imageNodes, 'group2')
};

const keyboardOperate = (graph) => {
	graph.bindKey(['meta+c', 'ctrl+c'], () => {
		const cells = graph.getSelectedCells()
		if (cells.length) {
			graph.copy(cells)
		}
		return false
	})
	graph.bindKey(['meta+x', 'ctrl+x'], () => {
		const cells = graph.getSelectedCells()
		if (cells.length) {
			graph.cut(cells)
		}
		return false
	})
	graph.bindKey(['meta+v', 'ctrl+v'], () => {
		if (!graph.isClipboardEmpty()) {
			const cells = graph.paste({ offset: 32 })
			graph.cleanSelection()
			graph.select(cells)
		}
		return false
	})

	// undo redo
	graph.bindKey(['meta+z', 'ctrl+z'], () => {
		if (graph.canUndo()) {
			graph.undo()
		}
		return false
	})
	graph.bindKey(['meta+shift+z', 'ctrl+shift+z'], () => {
		if (graph.canRedo()) {
			graph.redo()
		}
		return false
	})

	// select all
	graph.bindKey(['meta+a', 'ctrl+a'], () => {
		const nodes = graph.getNodes()
		if (nodes) {
			graph.select(nodes)
		}
	})

	// delete
	graph.bindKey(['delete', 'backspace'], () => {
		const cells = graph.getSelectedCells()
		if (cells.length) {
			graph.removeCells(cells)
		}
	})

	// zoom
	graph.bindKey(['ctrl+1', 'meta+1'], () => {
		const zoom = graph.zoom()
		if (zoom < 1.5) {
			graph.zoom(0.1)
		}
	})
	graph.bindKey(['ctrl+2', 'meta+2'], () => {
		const zoom = graph.zoom()
		if (zoom > 0.5) {
			graph.zoom(-0.1)
		}
	})
};



const initFlowCanvas = (container, nodes) => {
	let graph = new X6.Graph({
		container,
		grid: true,
		autoResize: true,
		translating: {
			restrict: true,
		},
		mousewheel: {
			enabled: true,
			zoomAtMousePosition: true,
			modifiers: 'ctrl',
			minScale: 0.5,
			maxScale: 3
		},
		connecting: {
			router: 'manhattan',
			connector: { name: 'rounded', args: { radius: 8 } },
			anchor: 'center',
			connectionPoint: 'anchor',
			allowBlank: false,
			snap: { radius: 20 },
			createEdge: createEdgeFunc,
			validateConnection({ targetMagnet }) {
				return !!targetMagnet
			},
		},
		highlighting: {
			magnetAdsorbed: {
				name: 'stroke',
				args: { attrs: { fill: color, stroke: color } }
			}
		}
	});
	graph.use(new Transform({ resizing: true, rotating: true }));
	graph.use(new Selection({ rubberband: true, showNodeSelectionBox: true }));
	graph.use(new Snapline());
	graph.use(new Keyboard());
	graph.use(new Clipboard());
	graph.use(new History());
	initFlowNodes(nodes, graph);
	keyboardOperate(graph);
	return graph;
}

export default initFlowCanvas;